package core;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;

/**
 * Evaluates whether the input strings matches SQL descriptions.
 * @author tchan
 *
 */
public class SqlEvaluator {

	private static final String FOREIGN_KEY = "FOREIGN KEY";
	private static final String COMMENT = "-";
	private static final String ALTER_TABLE = "ALTER TABLE";
	private static final String CREATE_TABLE = "CREATE TABLE";
	private static final String REFERENCES = " REFERENCES ";
	private static final String SPACE = " ";

	public boolean isBeginCreateStmt(final String stmt) {
		return startsWith(stmt, CREATE_TABLE);
	}

	public boolean isComment(final String stmt) {
		return startsWith(stmt, COMMENT);
	}

	public boolean isAlterStmt(final String stmt) {
		return startsWith(stmt, ALTER_TABLE);
	}

	public boolean endReached(final String stmt) {
		return contains(stmt, ";");
	}

	public boolean hasForeignKey(final String stmt) {
		return contains(stmt, FOREIGN_KEY);
	}

	public boolean hasReferenceToDependent(final String stmt) {
		return contains(stmt, REFERENCES);
	}

	private boolean contains(final String stmt, final String contains) {
		return StringUtils.containsIgnoreCase(stmt, contains);
	}

	private boolean startsWith(final String stmt, final String prefix) {
		return StringUtils.startsWithIgnoreCase(stmt.trim(), prefix);
	}

	public List<String> getDependentTables(final String stmt) {
		String[] splitArrayBasedOnReferencesKeyword = null;

		if (isCapitalized(stmt)) {
			splitArrayBasedOnReferencesKeyword = stmt.split(REFERENCES);

		} else {
			splitArrayBasedOnReferencesKeyword = stmt.split(REFERENCES.toLowerCase());
		}

		List<String> dependentEntries = filterContainingReferencedTableNames(splitArrayBasedOnReferencesKeyword);

		List<String> dependnentTableNames = new ArrayList<String>();

		for (String dependentEntry : dependentEntries) {
			dependnentTableNames.add(getReferencedTableName(dependentEntry));
		}

		return dependnentTableNames;

	}

	private String getReferencedTableName(final String dependentEntry) {
		return dependentEntry.split("\\(")[0].trim();
	}

	private List<String> filterContainingReferencedTableNames(final String[] splitArray) {

		List<String> dependentEntries = new ArrayList<String>();
		//get the odd ones as they contain the dependent table information.
		for (int i = 0; i < splitArray.length; i++) {
			if (isOdd(i)) {
				dependentEntries.add(splitArray[i]);
			}
		}
		return dependentEntries;
	}

	private boolean isOdd(final int i) {
		return !isZerothElement(i) && (i % 1 == 0);
	}

	private boolean isZerothElement(final int i) {
		if (i == 0) {
			return true;
		}
		return false;
	}

	private boolean isCapitalized(final String stmt) {
		return stmt.contains(REFERENCES.toUpperCase());
	}

	/**
	 * Gets the full create sql statement from the iterator
	 * @param beginOfStmt
	 * @param iterator
	 * @return
	 */
	public String getFullStmtInOneString(final String beginOfStmt, final Iterator<String> iterator) {

		if (endReached(beginOfStmt)) {
			return beginOfStmt;
		}
		StringBuilder builder = new StringBuilder(beginOfStmt);

		while (iterator.hasNext()) {
			String nextLine = iterator.next();

			builder.append(SPACE);
			builder.append(nextLine);

			if (endReached(nextLine)) {
				break;
			}

		}

		return builder.toString();
	}

	public String getTableToAddModify(final String stmt) {
		return stmt.trim().split(" ")[2];
	}

	/**
	 * Gets the table name from the create statement.
	 * Example is "Create table XXX".
	 * @param stmt TODO
	 */
	public String getTableNameFrom(final String stmt) {
		return stmt.trim().split(" ")[2];
	}
}
